VOC数据集格式转化成COCO数据集格式

您所在的位置:网站首页 coco voc 数据集 VOC数据集格式转化成COCO数据集格式

VOC数据集格式转化成COCO数据集格式

2022-06-09 00:09| 来源: 网络整理| 查看: 265

                  VOC数据集格式转化成COCO数据集格式 一、唠叨      之前写过一篇关于coco数据集转化成VOC格式的博客COCO2VOC,最近读到CenterNet的官方代码,实现上则是将voc转化成coco数据格式,这样的操作我个人感觉很不习惯,也觉得有些奇葩,可能是每个人习惯不一样吧,我们知道有时候我们会采用labelImg标注数据,标注出来的格式就是voc,如果直接训练就可以用来训练是不是更加友好。

     为了不大规模修改原始训练代码(虽然自己修改了一个版本的voc数据集就能直接训练centernet 😊),同时也看到网上很多大佬也做了将VOC数据格式转化成COCO用于其训练,这里我自己做一个精细一点的,作为笔记。

二、转化过程    数据格式的转换实际是annotation标注文件的转化,voc的数据标注文件为以.xml结尾的文件,而且每张图片均有一个对应的同名标注文件;COCO则是将所有的标注信息写在一个json文件中。VOC数据集目录如下:

    在之前的coco2voc博客中做了详细的介绍,现在直接开始转化,目标就是将Annotations中的所有标注文件中的bbox标注信息转化为json文件,根据训练集和测试集,则主要转化为四个json文件,分别是test.json、train.json、val.json和trainval.json .这里我根据ImageSets中的train.txt val.txt trainval.txt生成后三个json文件,当然也可以直接从Annotations文件夹生成。

VOC2COCO.py import xml.etree.ElementTree as ET import os import json   coco = dict() coco['images'] = [] coco['type'] = 'instances' coco['annotations'] = [] coco['categories'] = []   category_set = dict() image_set = set()   category_item_id = -1 image_id = 20180000000 annotation_id = 0   def addCatItem(name):     global category_item_id     category_item = dict()     category_item['supercategory'] = 'none'     category_item_id += 1     category_item['id'] = category_item_id     category_item['name'] = name     coco['categories'].append(category_item)     category_set[name] = category_item_id     return category_item_id   def addImgItem(file_name, size):     global image_id     if file_name is None:         raise Exception('Could not find filename tag in xml file.')     if size['width'] is None:         raise Exception('Could not find width tag in xml file.')     if size['height'] is None:         raise Exception('Could not find height tag in xml file.')     image_id += 1     image_item = dict()     image_item['id'] = image_id     image_item['file_name'] = file_name     image_item['width'] = size['width']     image_item['height'] = size['height']     coco['images'].append(image_item)     image_set.add(file_name)     return image_id   def addAnnoItem(object_name, image_id, category_id, bbox):     global annotation_id     annotation_item = dict()     annotation_item['segmentation'] = []     seg = []     # bbox[] is x,y,w,h     # left_top     seg.append(bbox[0])     seg.append(bbox[1])     # left_bottom     seg.append(bbox[0])     seg.append(bbox[1] + bbox[3])     # right_bottom     seg.append(bbox[0] + bbox[2])     seg.append(bbox[1] + bbox[3])     # right_top     seg.append(bbox[0] + bbox[2])     seg.append(bbox[1])       annotation_item['segmentation'].append(seg)       annotation_item['area'] = bbox[2] * bbox[3]     annotation_item['iscrowd'] = 0     annotation_item['ignore'] = 0     annotation_item['image_id'] = image_id     annotation_item['bbox'] = bbox     annotation_item['category_id'] = category_id     annotation_id += 1     annotation_item['id'] = annotation_id     coco['annotations'].append(annotation_item)   def _read_image_ids(image_sets_file):     ids = []     with open(image_sets_file) as f:         for line in f:             ids.append(line.rstrip())     return ids   """通过txt文件生成""" #split ='train' 'va' 'trainval' 'test' def parseXmlFiles_by_txt(data_dir,json_save_path,split='train'):     print("hello")     labelfile=split+".txt"     image_sets_file = data_dir + "/ImageSets/Main/"+labelfile     ids=_read_image_ids(image_sets_file)       for _id in ids:         xml_file=data_dir + f"/Annotations/{_id}.xml"           bndbox = dict()         size = dict()         current_image_id = None         current_category_id = None         file_name = None         size['width'] = None         size['height'] = None         size['depth'] = None           tree = ET.parse(xml_file)         root = tree.getroot()         if root.tag != 'annotation':             raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))           # elem is , , ,         for elem in root:             current_parent = elem.tag             current_sub = None             object_name = None               if elem.tag == 'folder':                 continue               if elem.tag == 'filename':                 file_name = elem.text                 if file_name in category_set:                     raise Exception('file_name duplicated')               # add img item only after parse tag             elif current_image_id is None and file_name is not None and size['width'] is not None:                 if file_name not in image_set:                     current_image_id = addImgItem(file_name, size)                     print('add image with {} and {}'.format(file_name, size))                 else:                     raise Exception('duplicated image: {}'.format(file_name))                     # subelem is , , , ,             for subelem in elem:                 bndbox['xmin'] = None                 bndbox['xmax'] = None                 bndbox['ymin'] = None                 bndbox['ymax'] = None                   current_sub = subelem.tag                 if current_parent == 'object' and subelem.tag == 'name':                     object_name = subelem.text                     if object_name not in category_set:                         current_category_id = addCatItem(object_name)                     else:                         current_category_id = category_set[object_name]                   elif current_parent == 'size':                     if size[subelem.tag] is not None:                         raise Exception('xml structure broken at size tag.')                     size[subelem.tag] = int(subelem.text)                   # option is , , , , when subelem is                 for option in subelem:                     if current_sub == 'bndbox':                         if bndbox[option.tag] is not None:                             raise Exception('xml structure corrupted at bndbox tag.')                         bndbox[option.tag] = int(option.text)                   # only after parse the tag                 if bndbox['xmin'] is not None:                     if object_name is None:                         raise Exception('xml structure broken at bndbox tag')                     if current_image_id is None:                         raise Exception('xml structure broken at bndbox tag')                     if current_category_id is None:                         raise Exception('xml structure broken at bndbox tag')                     bbox = []                     # x                     bbox.append(bndbox['xmin'])                     # y                     bbox.append(bndbox['ymin'])                     # w                     bbox.append(bndbox['xmax'] - bndbox['xmin'])                     # h                     bbox.append(bndbox['ymax'] - bndbox['ymin'])                     print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,                                                                    bbox))                     addAnnoItem(object_name, current_image_id, current_category_id, bbox)     json.dump(coco, open(json_save_path, 'w'))   """直接从xml文件夹中生成""" def parseXmlFiles(xml_path,json_save_path):     for f in os.listdir(xml_path):         if not f.endswith('.xml'):             continue           bndbox = dict()         size = dict()         current_image_id = None         current_category_id = None         file_name = None         size['width'] = None         size['height'] = None         size['depth'] = None           xml_file = os.path.join(xml_path, f)         print(xml_file)           tree = ET.parse(xml_file)         root = tree.getroot()         if root.tag != 'annotation':             raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))           # elem is , , ,         for elem in root:             current_parent = elem.tag             current_sub = None             object_name = None               if elem.tag == 'folder':                 continue               if elem.tag == 'filename':                 file_name = elem.text                 if file_name in category_set:                     raise Exception('file_name duplicated')               # add img item only after parse tag             elif current_image_id is None and file_name is not None and size['width'] is not None:                 if file_name not in image_set:                     current_image_id = addImgItem(file_name, size)                     print('add image with {} and {}'.format(file_name, size))                 else:                     raise Exception('duplicated image: {}'.format(file_name))                     # subelem is , , , ,             for subelem in elem:                 bndbox['xmin'] = None                 bndbox['xmax'] = None                 bndbox['ymin'] = None                 bndbox['ymax'] = None                   current_sub = subelem.tag                 if current_parent == 'object' and subelem.tag == 'name':                     object_name = subelem.text                     if object_name not in category_set:                         current_category_id = addCatItem(object_name)                     else:                         current_category_id = category_set[object_name]                   elif current_parent == 'size':                     if size[subelem.tag] is not None:                         raise Exception('xml structure broken at size tag.')                     size[subelem.tag] = int(subelem.text)                   # option is , , , , when subelem is                 for option in subelem:                     if current_sub == 'bndbox':                         if bndbox[option.tag] is not None:                             raise Exception('xml structure corrupted at bndbox tag.')                         bndbox[option.tag] = int(option.text)                   # only after parse the tag                 if bndbox['xmin'] is not None:                     if object_name is None:                         raise Exception('xml structure broken at bndbox tag')                     if current_image_id is None:                         raise Exception('xml structure broken at bndbox tag')                     if current_category_id is None:                         raise Exception('xml structure broken at bndbox tag')                     bbox = []                     # x                     bbox.append(bndbox['xmin'])                     # y                     bbox.append(bndbox['ymin'])                     # w                     bbox.append(bndbox['xmax'] - bndbox['xmin'])                     # h                     bbox.append(bndbox['ymax'] - bndbox['ymin'])                     print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,                                                                    bbox))                     addAnnoItem(object_name, current_image_id, current_category_id, bbox)     json.dump(coco, open(json_save_path, 'w'))       if __name__ == '__main__':     #通过txt文件生成     # voc_data_dir="E:/VOCdevkit/VOC2007"     # json_save_path="E:/VOCdevkit/voc2007trainval.json"     # parseXmlFiles_by_txt(voc_data_dir,json_save_path,"trainval")       #通过文件夹生成     ann_path="E:/VOCdevkit/VOC2007/Annotations"     json_save_path="E:/VOCdevkit/test.json"     parseXmlFiles(ann_path,json_save_path)

 生成之后就是这样:

到此就结束了,提供两个关键函数,一个是通过txt,另一个使用过文件夹,然后就可以用于centernet训练了,或者也可以用于其他的算法数据准备。

任何程序错误,以及技术疑问或需要解答的,请添加



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3